import json

from analyzer.addr2line_analyzer import Addr2LineAnalyzer


class PerfDumpAnalyzer:
    def __init__(self, file_path):
        self.file_path = file_path
        self.total_period = 0
        self.samples = []

    def analyze(self):
        with open(self.file_path, 'r') as f:
            self.samples = f.read().split('record sample:')[1:]
            self.samples[-1] = self.samples[-1].split('======= there are')[0]
            self.samples = ['record sample:' + e for e in self.samples]

        period_counts = {}
        for sample in self.samples:
            period = int(sample.split('period ')[-1].split('\n')[0])
            self.total_period += period
            for line in sample.split('\n'):
                if '@' not in line or '[kernel.kallsyms]' in line or line.count('@') > 1:
                    continue
                line_info = self._parse_file_path_func_addr(line)
                break
            period_counts[line_info] = period_counts.get(line_info, 0) + period

        sorted_period_counts = sorted(period_counts.items(), key=lambda x: x[1], reverse=True)
        percentage_period_counts = [(item[0][0], item[0][1], item[0][2], item[1], (item[1] / self.total_period) * 100)
                                    for item in sorted_period_counts]
        return percentage_period_counts

    def get_total_period(self):
        return self.total_period

    def _parse_file_path_func_addr(self, line):
        file_path = line.split('@')[-1].split(':')[0]
        func_info = line.split('@')[0].split(' : ')[-1]
        if '][+0x' in line:
            func = func_info.split('][+0x')[0].split('[')[0]
            addr = self._calculate_hex_address(func_info)
        else:
            func = func_info.split('+')[0]
            addr = func_info.split('+')[-1]
        return file_path, func, addr

    def _calculate_hex_address(self, func_info):
        base_addr = int(func_info.split(':')[-1].split('][+0x')[0], 16)
        offset = int(func_info.split('][+0x')[-1].split(']')[0], 16)
        return hex(base_addr + offset)
